package com.zzj.handle;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zzj.service.IChatFriendsService;
import com.zzj.service.IChatService;
import com.zzj.service.RedisService;
import com.zzj.utils.RedisUtil;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;


import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;


@Component
@Log4j2
@ServerEndpoint("/websocket/{fromUsername}/{toUsername}")
public class WebSocket {

    private static ConcurrentHashMap<String, Session> webSocketMap = new ConcurrentHashMap<>();
    /**
     * concurrent包的线程安全Map，用来存放每个客户端对应的MyWebSocket对象
     */

    private static IChatFriendsService chatFriendsService;
    private static IChatService chatService;
    private static RedisUtil redisUtil;

    private static RedisService redisService;


    private Session session;
    private String fromUsername;
    private String toUsername;

    public static void setChatFriendsService(IChatFriendsService chatFriendsService) {
        WebSocket.chatFriendsService = chatFriendsService;
    }

    public static void setChatService(IChatService chatService) {
        WebSocket.chatService = chatService;
    }

    public static void setRedisUtil(RedisUtil redisUtil) {
        WebSocket.redisUtil = redisUtil;
    }

    public static void setRedisService(RedisService redisService) {
        WebSocket.redisService = redisService;
    }


    @OnOpen
    public void onOpen(Session session,
                       @PathParam("fromUsername") String fromUsername,
                       @PathParam("toUsername") String toUsername) {
        this.session = session;
        this.fromUsername = fromUsername;
        this.toUsername = toUsername;
        webSocketMap.put(this.fromUsername, session);
        String item = toUsername + "," + fromUsername;
        redisService.setChatNoReadNum(item,0);
        log.info("用户{}连接成功", this.fromUsername);
    }

    @OnClose
    public void onClose() {
        webSocketMap.remove(fromUsername);
        log.info("用户{}关闭连接", fromUsername);
    }

    @OnMessage
    public void onMessage(String params) throws IOException {
        JSONObject data = JSONObject.parseObject(params);
        String message = data.getString("msg");
        int type = data.getIntValue("type");
        int size = data.getIntValue("size");
        log.info("来自客户端用户{}消息:{}发送给{},", fromUsername, message, toUsername);
        boolean isFriend = chatFriendsService.isFriend(fromUsername, toUsername);
        if (!isFriend) return;
        //在线
        if (webSocketMap.containsKey(toUsername)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("type","chat");
            jsonObject.put("username", fromUsername);
            jsonObject.put("message", message);
            jsonObject.put("chatType",type);
            jsonObject.put("size",size);
            webSocketMap.get(toUsername).getBasicRemote().sendText(JSON.toJSONString(jsonObject));
        }
        else{
            //不在线 redis缓存未读消息数量
            String item = fromUsername + ",间隔," + toUsername;
            int chatNoReadNum = redisService.getChatNoReadNum(item);
            if (chatNoReadNum!=0) {
                redisUtil.hincr("ChatNoReadNum", item, 1);
            } else {
                redisUtil.hset("ChatNoReadNum", item, 1);
            }
        }
        chatService.createChat(fromUsername, toUsername, message,type,size);
    }

    @OnError
    public void onError(Throwable error) {
        log.error("用户错误:" + fromUsername + ",原因:" + error.getMessage());
        error.printStackTrace();
    }

    /**
     * 系统发送
     *
     * 刷新
     */
    public void sendMessageByUsername(String username,String type, String message) throws IOException {
        log.info("服务端发送消息到{},消息：{}", username, message);
        if (StrUtil.isNotBlank(username) && webSocketMap.containsKey(username)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("type",type);
            jsonObject.put("message", message);
            webSocketMap.get(username).getBasicRemote().sendText(JSON.toJSONString(jsonObject));
        } else {
            log.error("用户{}不在线", username);
        }
    }


    public void sendComment(String username,int commentId) throws IOException {
        log.info("来自客户端用户{}评论给{},", fromUsername, username);
        String commentNoReadId = redisService.getCommentNoReadId(username);
        if(commentNoReadId!=null){
            redisService.setCommentNoReadId(username,commentNoReadId);
        }else{
            redisService.setCommentNoReadId(username,commentId+",");
        }
        if (StrUtil.isNotBlank(username) && webSocketMap.containsKey(username)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("username", fromUsername);
            jsonObject.put("type","comment");
            jsonObject.put("message", "新评论");
            webSocketMap.get(username).getBasicRemote().sendText(JSON.toJSONString(jsonObject));
        } else {
            log.error("用户{}不在线", username);
        }
    }
    public void sendReply(String username,int replyId) throws IOException {
        log.info("来自客户端用户{}回复给{},", fromUsername, username);
        String replyNoReadId = redisService.getReplyNoReadId(username);
        if(replyNoReadId!=null){
            redisService.setReplyNoReadId(username,replyNoReadId+replyId+",");
        }else{
            redisService.setReplyNoReadId(username,replyId+",");
        }
        if (StrUtil.isNotBlank(username) && webSocketMap.containsKey(username)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("username", fromUsername);
            jsonObject.put("type","reply");
            jsonObject.put("message", "新回复");
            webSocketMap.get(username).getBasicRemote().sendText(JSON.toJSONString(jsonObject));
        } else {
            log.error("用户{}不在线", username);
        }
    }

    public void sendLike(String username,int likeId) throws IOException {
        log.info("来自客户端用户{}点赞给{},", fromUsername, username);
        String likeNoReadId = redisService.getLikeNoReadId(username);
        if(likeNoReadId!=null){
            redisService.setLikeNoReadId(username,likeNoReadId+likeId+",");
        }else{
            redisService.setLikeNoReadId(username,likeId+",");
        }
        if (StrUtil.isNotBlank(username) && webSocketMap.containsKey(username)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("username", fromUsername);
            jsonObject.put("type","like");
            jsonObject.put("message", "新点赞");
            webSocketMap.get(username).getBasicRemote().sendText(JSON.toJSONString(jsonObject));
        } else {
            log.error("用户{}不在线", username);
        }
    }

    public void sendCancelLike(String username,int likeId) throws IOException {
        log.info("来自客户端用户{}取消点赞给{},", fromUsername, username);
        String likeNoReadId = redisService.getLikeNoReadId(username);
        if(likeNoReadId!=null){
            redisService.setLikeNoReadId(username,likeNoReadId.replace(likeId+",",""));
        }
        if (StrUtil.isNotBlank(username) && webSocketMap.containsKey(username)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("username", fromUsername);
            jsonObject.put("type","cancelLike");
            jsonObject.put("message", "取消点赞");
            webSocketMap.get(username).getBasicRemote().sendText(JSON.toJSONString(jsonObject));

        } else {
            log.error("用户{}不在线", username);
        }
    }

    public void sendNotice(String username) throws IOException {
        log.info("来自系统通告给{},", username);
        if (StrUtil.isNotBlank(username) && webSocketMap.containsKey(username)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("type","notice");
            jsonObject.put("message", "新公告");
            webSocketMap.get(username).getBasicRemote().sendText(JSON.toJSONString(jsonObject));
        } else {
            log.error("用户{}不在线", username);
        }
    }

    public void sendAllNotice() throws IOException {
        log.info("来自系统给所有人");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type","notice");
        jsonObject.put("message", "新公告");
        for (Session item : webSocketMap.values()) {
            item.getBasicRemote().sendText(JSON.toJSONString(jsonObject));
        }
    }

    public void sendCancelNotice(String username) throws IOException {
        log.info("来自系统谁撤销通告给{},", username);
        if (StrUtil.isNotBlank(username) && webSocketMap.containsKey(username)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("type","cancelNotice");
            jsonObject.put("message", "撤销公告");
            webSocketMap.get(username).getBasicRemote().sendText(JSON.toJSONString(jsonObject));
        } else {
            log.error("用户{}不在线", username);
        }
    }

    public void sendCancelAllNotice() throws IOException {
        log.info("来自系统撤销给所有人");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type","cancelNotice");
        jsonObject.put("message", "撤销公告");
        for (Session item : webSocketMap.values()) {
            item.getBasicRemote().sendText(JSON.toJSONString(jsonObject));
        }
    }
}
